package net.xdclass.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import net.xdclass.config.RabbitMqConfig;
import net.xdclass.enums.BizCodeEnum;
import net.xdclass.enums.ProductOrderStateEnum;
import net.xdclass.enums.StockStateEnum;
import net.xdclass.exception.BizException;
import net.xdclass.feign.ProductOrderFeignService;
import net.xdclass.mapper.ProductMapper;
import net.xdclass.mapper.ProductTaskMapper;
import net.xdclass.model.ProductDO;
import net.xdclass.model.ProductMessage;
import net.xdclass.model.ProductTaskDO;
import net.xdclass.request.LockProductRequest;
import net.xdclass.request.OrderItemRequest;
import net.xdclass.service.ProductService;
import net.xdclass.util.JsonData;
import net.xdclass.vo.ProductVO;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author 二当家小D
 * @since 2021-06-02
 */
@Service
@Slf4j
public class ProductServiceImpl  implements ProductService {
    @Autowired
    private ProductMapper productMapper;

    @Autowired
    private ProductTaskMapper productTaskMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private RabbitMqConfig rabbitMqConfig;

    @Autowired
    private ProductOrderFeignService productOrderFeignService;

    /**
     * 分页查询商品
     * @param page
     * @param size
     * @return
     */
    @Override
    public Map<String, Object> page(int page, int size) {
        Page<ProductDO> pageInfo = new Page<>(page,size);
        IPage<ProductDO> iPage = productMapper.selectPage(pageInfo, new QueryWrapper<ProductDO>());
        Map<String,Object> map = new HashMap<>();
        map.put("total_record", iPage.getTotal());
        map.put("total_page", iPage.getPages());
        map.put("current_data",  iPage.getRecords().stream().map(obj -> {
            return beanProcess(obj);
        }).collect(Collectors.toList()));
        return map;
    }

    /**
     * 根据产品id找商品详情
     * @param productId
     * @return
     */
    @Override
    public ProductVO detail(long productId) {
        ProductDO productDO = productMapper.selectById(productId);
        return beanProcess(productDO);
    }

    /**
     * 根据产品id list 批量查询产品
     * @param productIdList
     * @return
     */
    @Override
    public List<ProductVO> selectProductByIdList(List<Long> productIdList) {
        List<ProductDO> productDOList = productMapper.selectList(new QueryWrapper<ProductDO>().in("id", productIdList));
        List<ProductVO> productVOList = productDOList.stream().map(obj -> (beanProcess(obj))).collect(Collectors.toList());
        return productVOList;
    }

    /**
     * 锁库存
     *
     * @param lockProductRequest
     * @return
     */
    @Override
    public JsonData lockProducts(LockProductRequest lockProductRequest) {

        String orderOutTradeNo = lockProductRequest.getOrderOutTradeNo();
        List<OrderItemRequest> orderItemList = lockProductRequest.getOrderItemList();
        //将产品id抽离出来
        List<Long> productIdList = orderItemList.stream().map(OrderItemRequest::getProductId).collect(Collectors.toList());
        //批量查询产品
        List<ProductVO> productVOList = this.selectProductByIdList(productIdList);
        //分组
        Map<Long, ProductVO> maps = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));
        for (OrderItemRequest orderItemRequest : orderItemList) {
            int row = productMapper.lockStock(orderItemRequest.getProductId(), orderItemRequest.getBuyNum());
            if (row != 1) {
                throw new BizException(BizCodeEnum.ORDER_CONFIRM_LOCK_PRODUCT_FAIL);
            } else {
                ProductVO productVO = maps.get(orderItemRequest.getProductId());
                ProductTaskDO productTaskDO = new ProductTaskDO();
                productTaskDO.setProductId(orderItemRequest.getProductId());
                productTaskDO.setBuyNum(orderItemRequest.getBuyNum());
                productTaskDO.setLockState(StockStateEnum.LOCK.name());
                productTaskDO.setOutTradeNo(orderOutTradeNo);
                productTaskDO.setProductName(productVO.getTitle());
                productTaskMapper.insert(productTaskDO);
                
                //发送Mq延迟消息，商品库存
                ProductMessage productMessage = new ProductMessage();
                productMessage.setOutTradeNo(orderOutTradeNo);
                productMessage.setTaskId(productTaskDO.getId());
                rabbitTemplate.convertAndSend(rabbitMqConfig.getEventExchange(), rabbitMqConfig.getStockReleaseDelayRoutingKey(), productMessage);
                log.info("商品库存锁定消息延迟信息发送成功:{}",productMessage);
            }
        }
        return null;
    }

    /**
     * 释放库存
     * @param productMessage
     * @return
     */
    @Override
    public boolean releaseStockRecord(ProductMessage productMessage) {
        //查询task工作单是否存在
        ProductTaskDO productTaskDO = productTaskMapper.selectOne(new QueryWrapper<ProductTaskDO>().eq("id", productMessage.getTaskId()));
        if (productTaskDO == null) {
            log.warn("工作单不存在,消息{}",productMessage);
            return true;
        }
        //lock状态才处理
        if (productTaskDO.getLockState().equalsIgnoreCase(StockStateEnum.LOCK.name())) {
            //查询订单状态
            JsonData jsonData = productOrderFeignService.queryProductOrderState(productMessage.getOutTradeNo());
            if (jsonData.getCode() == 0) {
                //正常响应 判断订单状态
                String state = jsonData.getData().toString();
                if (ProductOrderStateEnum.NEW.name().equalsIgnoreCase(state)) {
                    //状态为new，需要返回false 让消息重新返回到消息队列
                    log.warn("订单状态为new，返回给消息队列重新投递，消息={}",productMessage);
                    return false;
                }
                //如果是已经支付了
                if (ProductOrderStateEnum.PAY.name().equalsIgnoreCase(state)) {
                    //修改task状态为finish
                    productTaskDO.setLockState(StockStateEnum.FINISH.name());
                    productTaskMapper.update(productTaskDO, new QueryWrapper<ProductTaskDO>().eq("id", productMessage.getTaskId()));
                    log.info("订单已经支付，修改库存锁定工作单FINISH状态:{}",productMessage);
                    return true;
                }
            }
            //订单不存在，或者订单被取消，确认消息，修改task状态为CANCEL,恢复库存
            log.warn("订单不存在，或者订单被取消，确认消息，修改task状态为CANCEL,库存恢复,message={}",productMessage);
            productTaskDO.setLockState(StockStateEnum.CANCEL.name());
            productTaskMapper.update(productTaskDO, new QueryWrapper<ProductTaskDO>().eq("id", productMessage.getTaskId()));
            //给库存解锁
            productMapper.uplockProductStock(productTaskDO.getProductId(),productTaskDO.getBuyNum());
            return true;
        } else {
            log.warn("工作单状态不是lock,state={},消息体={}",productTaskDO.getLockState(),productMessage);
            return true;
        }
    }

    private ProductVO beanProcess(ProductDO productDO) {
        ProductVO productVO = new ProductVO();
        BeanUtils.copyProperties(productDO, productVO);
        productVO.setStock(productDO.getStock()-productDO.getLockStock());
        return productVO;
    }
}
